package com.example.travelgd.config;

import com.example.travelgd.util.FwResult;
import com.example.travelgd.util.JwtConstant;
import com.example.travelgd.util.JwtUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);

    @Autowired
    RedisTemplate<String, Object> redisTemplate;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    // 需要登录才能访问的接口
    private final List<String> PROTECTED_PATHS = Arrays.asList(
            "/api/user/**",          // 用户相关
            "/api/reservation/**",    // 预约相关
            "/api/comment/**",        // 评论相关
            "/api/favorite/**"        // 收藏相关
    );

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        logger.debug("当前请求路径: {}", requestURI);

        // 如果不是需要保护的路径，直接放行
        if (!isProtectedPath(requestURI)) {
            logger.debug("非受保护路径，直接放行");
            filterChain.doFilter(request, response);
            return;
        }

        // 以下是需要登录才能访问的路径的处理逻辑
        String token = request.getHeader(JwtConstant.HEADER_NAME);
        response.setCharacterEncoding("UTF-8");

        if (!StringUtils.hasText(token)) {
            logger.debug("token不存在");
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "请先登录");
            return;
        }

        if (!JwtUtil.verifyToken(token)) {
            logger.debug("token验证失败");
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "token验证失败");
            return;
        }

        Object tokenObject = redisTemplate.opsForValue().get(token);
        if (tokenObject == null) {
            logger.debug("token在Redis中不存在");
            sendErrorResponse(response, HttpStatus.UNAUTHORIZED, "登录过期，请重新登录");
        } else {
            logger.debug("token验证成功，刷新过期时间");
            redisTemplate.expire(token, 30, TimeUnit.MINUTES);
            filterChain.doFilter(request, response);
        }
    }

    private boolean isProtectedPath(String requestURI) {
        boolean result = PROTECTED_PATHS.stream().anyMatch(pattern -> {
            boolean matches = pathMatcher.match(pattern, requestURI);
            logger.debug("检查路径 {} 是否需要保护 {}: {}", requestURI, pattern, matches);
            return matches;
        });
        logger.debug("是否是受保护的路径: {}", result);
        return result;
    }

    private void sendErrorResponse(HttpServletResponse response, HttpStatus status, String message) throws IOException {
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(status.value());
        ObjectMapper objectMapper = new ObjectMapper();
        String result = objectMapper.writeValueAsString(FwResult.failedMsg(message));
        response.getWriter().write(result);
    }
}